<template>
	
		<z-paging ref="paging" v-model="messages" :auto="false" use-page-scroll use-chat-record-mode @query="queryList">
			<view :id="`z-paging-${index}`" v-for="(message,index) in messages" :key="message.id" style="display: flex;padding: 5px;margin-bottom: 20px;"
				:style="{
					alignSelf: message.id%2 == 0?'flex-start':'flex-end',
					flexDirection:message.id%2 == 0?  'row' : 'row-reverse'
				}"
			>
				<view style="padding:5px">
					<u-avatar  :src="absUrl('/static/avatars/1.jpg')"></u-avatar>
				</view>
				<view style="display: flex;flex-direction: column;"
					:style="{
						alignItems: message.id%2 == 0?'flex-start':'flex-end'
					}"
				>
					<view style="padding: 5px 0;font-size: 22rpx;color:#999">2023-08-26 18:48:53</view>
					
					<!-- 消息区域 -->
					<view style="display: flex;align-items: center;"
						:style="{
							flexDirection:message.id%2 == 0?  'row' : 'row-reverse'
						}"
					>
						<!-- 消息框 -->
						<view style="box-shadow: 0 0px 8px 0px #66666622;">
							<!-- 文字消息 -->
							<view v-if="message.type == 'text'" style="font-size:16px;padding: 10px;border-radius: 8px;background-color: white;max-width: 285px;">
								<text :selectable="true">{{message.content.text}}</text>
							</view>
							
							<!-- 图片消息 -->
							<view v-if="message.type == 'img'" style="padding: 0px;border-radius: 5px;background-color: white;">
								<u--image  :src="message.message_size?absUrl(message.content.src):''" 
									:width="messageSize(message).width" 
									:height="messageSize(message).height" 
									@click="onPreview(absUrl(message.content.src))">
								</u--image>
							</view>
							
							<!-- 视频消息 -->
							<view v-if="message.type == 'video'" @click="previewVideo(message)" style="padding: 0px;border-radius: 5px;background-color: white;position: relative;">
								<u--image  :src="videoThumb(message)" 
									:width="messageSize(message).width" 
									:height="messageSize(message).height" 
									>
								</u--image>
								
								<view v-if="videoThumb(message) != ''" style="position: absolute;left: 50%;top:50%;transform: translate(-50%,-50%);">
									<u-icon name="play-circle" color="white" size="45"></u-icon>
								</view>
							</view>
							
							<!-- 文件 -->
							<view v-if="message.type == 'file'" @click="previewVideo(message)" style="padding: 0px;border-radius: 5px;background-color: white;position: relative;">
								<view style="width: 250px;height:100px;padding: 15px 10px;overflow: hidden;">
									<view style="display: flex;">
										<view style="flex:0;margin-right:10px">
											<u--image  :src="absUrl('/static/file-icon.png')"
												mode="widthFix"
												:width="30"
												:height="38"
											>
											</u--image>
										</view>
										<view style="flex:1;">{{message.content.name}}</view>
									</view>
								</view>
							</view>
						</view>
						
						<view v-if="message.isSend" style="padding: 5px;">
							<u-loading-icon size="14"></u-loading-icon>
						</view>
					</view>
					
				</view>
			</view>
			
			<!-- 底部聊天输入框 -->
			<template #bottom>
				<!-- 输入区域 -->
				<view style="width: 100%" @touchmove.stop.prevent="void 0">
					<view style="height: 60px;background-color: #f8f8f8;display: flex;justify-content: space-between;align-items: center;border-top: solid 1rpx #eee;">
						<!-- 左按钮 -->
						<view @click="onClickToolsButton" style="padding:10px;margin: 0 10px;background-color: #fff;border-radius: 100px;box-shadow: 0 0 3px 0px #66666622;border: solid 1rpx #eee;">
							<u-icon name="list"></u-icon>
						</view>
						
						<view style="
							flex:1;
							height:35px;
							margin:10px 0;
							background-color: blue;
							border-radius: 5px;
							display: flex;
							justify-content: flex-start;
							align-items: center;
							background-image: linear-gradient(45deg,#ffffff,#ffffff);
							text-align: left; 
							
						">
							<view style="padding: 0 0px;width: 100%;">
								<u--input v-model="textInput" placeholder="输入文本消息" :adjustPosition="false" @focus="on_inputFocus"></u--input> <!--@blur="onInputBlur"-->
							</view>
						</view>
						
						<view @click="sendText" style="
							width: 80px;
							height:35px;
							margin:10px;
							background-color: blue;
							border-radius: 80px;
							display: flex;
							justify-content: center;
							align-items: center;
							background-color: white;
							box-shadow: 0 0 3px 0px #66666622;
						">
							发送
						</view>
					</view>
					
					<!-- 工具箱 -->
					<!-- v-if="showTools" -->
					<view v-if="showTools" style="height: 200px;width: 100%;background-color: #eee;">
						<view style="width: 100%;height: 100%;padding: 10px;">
							<fields @icon-click="onIconClick"></fields>
						</view>
					</view>
				</view>
			</template>
			<!-- 输入区衬底 -->
			<view
				:style="{
					height:showTools? '200px':'0px'
				}"
			></view>
		</z-paging>
		
		
	<!-- 视频预览 -->
	<u-overlay :show="showPreviewVideo" @click="clickOverlay" :customStyle="{zIndex:9999}">
		<view v-if="showPreviewVideo" style="position: absolute;left: 50%;top:50%;transform: translate(-50%,-50%);" @longpress="longPressVideo" @click.native.stop="">
				<!-- <view style="color:white">HAHA--{{selectedMessage}}</view> -->
			<video
				:src="absUrl(selectedMessage.content.src)" 
				controls
				autoplay
				http-cache
				:poster="selectedMessage.thumb"
				:style="{
					width :previewSize(selectedMessage).width + 'px',
					height:previewSize(selectedMessage).height + 'px'
				}"
			></video>
		</view>
	</u-overlay>
</template>
 
<script>
	import fields from './fields.vue'
	export default {
		components:{fields},
		computed:{
			messageSize() {
				return (message)=>{
					return message.message_size ? message.message_size : {width:100,height:100}
				}
			},
			previewSize() {
				return (message)=>{
					return message.preview_size ? message.preview_size : {width:300,height:200}
				}
			},
			videoThumb() {
				return (message)=>{
					return message.content.thumb ? message.content.thumb : ''
				}
			}
		},
		data() {
			return {
				topic:null,
				showTools:false,
				//_inputFocus:false,
				showPreviewVideo:false,
				textInput:'',
				selectedMessage:null,
				messages:[],
				picCache:{},
				messages_raw:[
					{
						type:'text',
						content:{
							text:'大家好',
						}
					},
					{
						type:'img',
						content:{
							src:'/static/avatar.jpg',
						}
					},
					{
						type:'img',
						content:{
							src:'/static/h.jpg'
						}
					},
					{
						type:'img',
						content:{
							src:'/static/error.png',
						}
					},
					{
						type:'img',
						content:{
							src:'/static/mm.png',
						}
					},
					{
						type:'video',
						content:{
							src:'/static/vv.mp4',
						}
					},
					{
						type:'video',
						content:{
							src:'/static/kk.mp4',
						}
					},
					{
						type:'img',
						content:{
							src:'/static/logo.png',
						}
					}
				]
			}
		},
		onPageScroll(e) {
			//如果滚动到顶部，触发加载更多聊天记录
			if (e.scrollTop < 10) {
				this.$refs.paging.doChatRecordLoadMore();
			}
		},
		async onLoad(options) {
			const that = this
			console.log(options)
			
			if(options.topic)	
			{
				this.topic = options.topic
				console.log(options.topic)
				console.log('开始【监听】主题:' + this.topic)
				this.$chatService.on(options.topic,async (message)=>{
					console.log(message)
					let message_raw = await that.handleRawMessage([JSON.parse(message)])
					
					that.$refs.paging.addChatRecordData(message_raw[0]);
				})
			}
		},
		onUnload(){
			if(this.topic)
			{
				console.log('开始【移除】主题:' + this.topic)
				this.$chatService.off(this.topic)
			}
		},
		onShow(){
			console.log('FFFFFFFFFFFFKKK')
			const that = this
			
			this.$nextTick(async ()=>{
				//that.$refs.paging.reload();
				
				let message_raws = await that.handleRawMessage(that.messages_raw)
				that.$refs.paging.addChatRecordData(message_raws);
				
				let key = `chat-storage:${this.topic}`
				console.log(key)
				
				message_raws = this.$chatService.messagesWithTopic(this.topic)
				
				console.log(message_raws)
				
				message_raws = await this.handleRawMessage(message_raws)
				
				that.$refs.paging.addChatRecordData(message_raws.reverse());
			})
		},
		methods: {
			async onIconClick(item){
				
				if(item.type == 'image')
				{
					let url = await this.chooseImageToUpload()
					if(!url) return
					console.log(url)
					this._sendText('img',{src:url})
				}else if(item.type == 'video')
				{
					let url = await this.chooseVideoToUpload()
					if(!url) return
					console.log(url)
					this._sendText('video',{src:url})
				}
				
				this.showTools = false
				
				// this.$netTool.handleUploadFile()
			},
			async handleRawMessage(messages_raw){
				
				let promises = []
				let len = this.messages.length
				let n = 0
				messages_raw.forEach((message)=>{

					message.id = message.id ? message.id : len + (++n)
					
					if(message.type == 'text')
						return
						
					promises.push(this.regularMessageSize(message))
				})
				
				await Promise.all(promises)
				
				return messages_raw
			},
			async handleNetMessage(messages_net){
				
				let promises = []

				messages_net.forEach((message)=>{
					message.content = JSON.parse(message.content)
					
					if(message.type == 'text')
						return
						
					promises.push(this.regularMessageSize(message))
				})

				await Promise.all(promises)
				
				return messages_net
			},
			async loadMessage(pageNo, pageSize){
				
				//let messages_raw = JSON.parse(JSON.stringify(this.messages_raw))

				// let res = await this.$http.get('/common/chat/list',{
				// 	params:{
				// 		page:pageNo,
				// 		size:pageSize
				// 	}
				// })
				
				// let messages_net = await this.handleNetMessage(res.data.data)

				this.$refs.paging.complete([]); //,...messages_net]
			},
			queryList(pageNo, pageSize) {
				this.loadMessage(pageNo, pageSize)
			},
			onClickToolsButton(){
				this.showTools = !this.showTools
				this.scrollToBottom(100,0)
			},
			longPressVideo(){
				uni.showActionSheet({
					itemList:[
						'下载视频',
						'转发视频'
					]
				})
			},
			scrollToBottom(duration=100,timeout=100)
			{
				setTimeout(()=>{
					uni.pageScrollTo({
						scrollTop:2000000,
						duration
					})
				},timeout)
			},
			async previewVideo(message){
				await this.regularPreviewSize(message)
				
				this.selectedMessage = message
				this.showPreviewVideo = true
			},
			clickOverlay(){
				this.showPreviewVideo = false
				
				let that = this
				this.$nextTick(()=>{
					that.selectedMessage = null
				})
			},
			async ensureSizeInfo(message)
			{
				if(message.size) return
				
				let imgInfo = null
				
				switch(message.type)
				{
					case 'img':
						imgInfo = await uni.getImageInfo({
							src: this.absUrl(message.content.src)
						})
						break;
					case 'video':
						imgInfo = await uni.getVideoInfo({
							src: this.absUrl(message.content.src)
						})

						message.content.thumb = await this.getVideoPoster(message,imgInfo.width,imgInfo.height)
						break;
				}
				
				message.size = {width:imgInfo.width,height:imgInfo.height}
			},
			async regularSize(message,maxWidth=200,maxHeight=150)
			{
					try{
						await this.ensureSizeInfo(message)
					}catch(e){
						//TODO handle the exception
						message.size = {width:200,height:200}
					}
					
					// console.log(message.size)
					
					// let length = Math.max(message.size.width,message.size.height)
					// let scale = Math.min(maxWidth / length,1.0)
					
					let widthScale = Math.min(maxWidth / message.size.width,1.0)
					let heightScale = Math.min(maxHeight / message.size.height,1.0)
					let scale = Math.min(widthScale,heightScale,1.0)
					
					// let length = Math.max(message.size.width,message.size.height)
					// let scale = Math.min(maxLength / length,1.0)
					
					let width = Math.floor(message.size.width * scale)
					let height = Math.floor(message.size.height * scale)
					
					width = Math.max(width,30)
					height = Math.max(height,30)
					 
					// console.log(message.size)
					// console.log(width)
					// console.log(height)

					return {width,height}
			},			
			async regularPreviewSize(message){
				console.log(this.$device.screenWidth())
				message.preview_size = await this.regularSize(message,this.$device.screenWidth(),this.$device.measure.windowHeight * 0.8)
			},		
			async regularMessageSize(message){
				message.message_size = await this.regularSize(message,200)
			},
			onPreview(absUrl){
				uni.previewImage({
					urls:[absUrl]
				})
			},
			async sendText(e){
				let textInput = this.textInput
				
				if(!!!textInput) return 
				
				this._sendText('text',{text:textInput})
				
				// this.$refs.paging.addChatRecordData({
				// 	id:9999,
				// 	type:'file',
				// 	content:{
				// 		name:'苍井.png',
				// 		url:'files/abc.png'
				// 	}
				// });
			},
			async _sendText(type,content){
		
				this.textInput = ''
				let id = this.messages.length > 0 ? this.messages[this.messages.length - 1].id + 1 : 1
				console.log(id)
				
				let message = {
					id,
					type,
					//isSend:true,
					content
				}

				this.$chatService.publish(this.topic,JSON.stringify(message))
				
				// let message_raw = await this.handleRawMessage([message])
				
				// this.$refs.paging.addChatRecordData(message_raw[0]);
				
				// let res = await this.$http.post('/common/chat/create',{
				// 	message
				// })
				
				// console.log(res.data)
				
				// message = this.messages[this.messages.length - 1]
				// message.isSend = false
				// Object.assign(message,{id:res.data.id})
				
				// let message_raw = await this.handleNetMessage([res.data])
				
				// uni.hideLoading();
				
				//this.textInput = ''

				this.scrollToBottom(100,100)
			},
			// H5 键盘状态不可预见,不要根据键盘状态做任何区域控制。
			on_inputFocus(){
				this.showTools = false

				//this.scrollToBottom(0,100)
				
				//this.scrollToBottom(100,200)
			},
			// onInputBlur(){
			// 	let that = this
			// 	this.$nextTick(()=>{
			// 		that._inputFocus = false
			// 		uni.showToast({
			// 			title:'blur2'
			// 		})
			// 	})
			// },
			async getVideoPoster(message,width=200,height=200) {
			  let poster = this.picCache[message.content.src]
			  
			  
			  if(poster)
			  {
				  if(typeof(poster) == 'string')
				   {
					   return poster 
				   }else
				   {
					   try {
						   let url = await poster
						   return url
					   }catch(e){
						   console.log(e)
						   return null
					   }
				   }
			  }
			  
			  //const that = this;
			  let dataURL = null
			  //let video = uni.createVideoContext('video-for-draw')
			  let video = document.createElement('video')
			  video.setAttribute('crossOrigin', 'anonymous') // 处理跨域，H5需后台支持，请求的视频资源响应投标需有Access-Control-Allow-Origin
			  video.setAttribute('src', this.absUrl(message.content.src))
			  video.setAttribute('width', width)
			  video.setAttribute('height', height)
			  video.setAttribute('preload', 'auto')
			  
			  // console.log('开始加载视频:' + message.content.src)
			  // uni.chooseVideo选择视频，当选用手机拍摄的视频时，地址是相对地址，如 _doc/uniapp_temp_1650594368317/camera/1650594390147.mp4
			  // 可播放，但是loadeddata一直不执行，会触发error事件，视频加载失败
			  // 应先转换成本地地址
			
			  let that = this
			  let promise = new Promise((resolve,reject)=>{
				  //上传文件
				   function dataURLtoFile(file,filename) {
				      const arr = file.split(',');
				      const mime = arr[0].match(/:(.*?);/)[1];
				      const bstr = atob(arr[1]);
					  // console.log(bstr)
				      let n = bstr.length;
				      const u8arr = new Uint8Array(n);
				      while (n--) {
				        u8arr[n] = bstr.charCodeAt(n);
				      }
				  
				      return new File([u8arr], filename, {type: mime});
				   }
				  			
				  let blob = null
				  
				  video.addEventListener('loadeddata', function () {
						console.log('视频第一帧加载完:' + message.content.src)
						let canvas = document.createElement('canvas')
						let width = video.width // canvas的尺寸和图片一样
						let height = video.height
						canvas.width = width
						canvas.height = height
						canvas.getContext('2d').drawImage(video, 0, 0, width, height) // 绘制canvas
						dataURL = canvas.toDataURL('image/jpeg') // 转换为base64
					  
						console.log('getVideoPoster-dataURL', dataURL.slice(0, 16)) 
						blob = dataURLtoFile (dataURL,'video.png');
						let url = window.URL.createObjectURL(blob)
						
						that.picCache[message.content.src] = url
						console.log(that.picCache)
						resolve(url)
				  })
				  
				  video.addEventListener('error', err => {
						console.log('视频加载失败', err)
						reject(err)
				  })
			  })
			  
			  that.picCache[message.content.src] = promise
			  let url = await promise
			  that.picCache[message.content.src] = url
			  return url
			}
		}
	}
</script>

<style scoped>
	page {
		/* background-image: linear-gradient(45deg,#f4ffd5,#ffe5d5); */
		background-color: #fafafa;
	}
</style>
